package com.example.facility.service.facility;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.example.facility.common.PageResult;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.facility.common.LocalDateTimeUtil;
import com.example.facility.controller.admin.facility.vo.FacilityPageReqVO;
import com.example.facility.controller.admin.facility.vo.FacilitySaveReqVO;
import com.example.facility.controller.admin.facility.vo.FacilityUpdateReqVO;
import com.example.facility.dal.dataobject.facility.FacilityDO;
import com.example.facility.dal.dataobject.receivereturn.ReceiveReturnDO;
import com.example.facility.dal.dataobject.user.UserDO;
import com.example.facility.dal.mysql.FacilityMapper;
import com.example.facility.emun.TypeEnum;
import com.example.facility.emun.YesNoEnum;
import com.example.facility.service.receivereturn.ReceiveReturnService;
import com.example.facility.service.user.UserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;


/**
 * 设备管理 Service 实现类
 *
 * @author lwb
 */
@Service
@Validated
public class FacilityServiceImpl extends ServiceImpl<FacilityMapper, FacilityDO> implements FacilityService {

    @Resource
    private FacilityMapper facilityMapper;

    @Resource
    private ReceiveReturnService returnService;

    @Resource
    private UserService userService;

    @Override
    public Long createFacility(FacilitySaveReqVO createReqVO) {
        //编码检验
        checkName(createReqVO);

        // 插入
        FacilityDO facilityDO = new FacilityDO();
        BeanUtil.copyProperties(createReqVO, facilityDO);
        facilityDO.setId(IdUtil.getSnowflakeNextId());
        facilityDO.setCreateTime(LocalDateTimeUtil.convertStr());
        facilityDO.setUpdateTime(LocalDateTimeUtil.convertStr());
        facilityMapper.insert(facilityDO);
        // 返回
        return facilityDO.getId();
    }


    public void checkName(FacilitySaveReqVO reqVO) {
        if (StrUtil.isBlank(reqVO.getName())) {
            throw new RuntimeException("设备名称不能为空");
        }
        if (StrUtil.isBlank(reqVO.getNo())) {
            throw new RuntimeException("设备编号不能为空");
        }
        if (StrUtil.isBlank(reqVO.getCategoryName())) {
            throw new RuntimeException("设备类型不能为空");
        }
        //编码唯一
        LambdaQueryWrapper<FacilityDO> lqw = new LambdaQueryWrapper<>();
        lqw.eq(FacilityDO::getNo, reqVO.getNo());
        if (reqVO.getId() != null) {
            lqw.ne(FacilityDO::getId, reqVO.getId());
        }
        FacilityDO facilityDO = facilityMapper.selectOne(lqw);

        if (facilityDO != null) {
            throw new RuntimeException("设备编号已存在");
        }
    }

    @Override
    public void updateFacility(FacilitySaveReqVO updateReqVO) {
        //编码检验
        checkName(updateReqVO);

        // 校验存在
        validateFacilityExists(updateReqVO.getId());
        FacilityDO facilityDO = new FacilityDO();
        facilityDO.setUpdateTime(LocalDateTimeUtil.convertStr());
        BeanUtil.copyProperties(updateReqVO, facilityDO);

        facilityMapper.updateById(facilityDO);
    }

    @Override
    public void deleteFacility(Long id) {
        // 校验存在
        validateFacilityExists(id);
        // 删除
        facilityMapper.deleteById(id);
    }

    private void validateFacilityExists(Long id) {
        if (facilityMapper.selectById(id) == null) {

        }
    }

    @Override
    public FacilityDO getFacility(Long id) {
        return facilityMapper.selectById(id);
    }

    @Override
    public List<FacilityDO> getFacilityPage(FacilityPageReqVO pageReqVO) {
        //设置分页参数
//        Page<FacilityDO> page = new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize());
//        Page<FacilityDO> pageResult = facilityMapper.selectPageVo(page, pageReqVO);
//        if (pageResult != null) {
//            PageResult<FacilityDO> result = new PageResult<>();
//            result.setList(pageResult.getRecords());
//            result.setTotal(pageResult.getTotal());
//            return result;
//        }
//        return new PageResult<>();
        LambdaQueryWrapper<FacilityDO> lqw = new LambdaQueryWrapper<>();
        if (StrUtil.isNotBlank(pageReqVO.getName())) {
            lqw.and(w -> w.eq(FacilityDO::getName, pageReqVO.getName()).or().eq(FacilityDO::getNo, pageReqVO.getName()));
        }
        lqw.orderByDesc(FacilityDO::getId);
        return facilityMapper.selectList(lqw);
    }

    /**
     * 获取用户已领用列表
     *
     * @param userId
     * @return
     */
    @Override
    public List<FacilityDO> getUserFacilityList(Long userId) {
        LambdaQueryWrapper<FacilityDO> lqw = new LambdaQueryWrapper<>();
        lqw.eq(FacilityDO::getUserId, userId);
        lqw.eq(FacilityDO::getStatus, YesNoEnum.YES.getType());
        return facilityMapper.selectList(lqw);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateFacilityStatus(FacilityUpdateReqVO updateReqVO) {

        if (CollUtil.isEmpty(updateReqVO.getIds())) {
            throw new RuntimeException("设备ids不能为空");
        }

        if (updateReqVO.getType() == null) {
            throw new RuntimeException("设备状态不能为空->状态(1领用 2归还)");
        }

        if (Objects.equals(updateReqVO.getType(), TypeEnum.RECEIVE.getType()) && updateReqVO.getUserId() == null) {
            //领用必须有用户
            throw new RuntimeException("用户Id不能为空");
        }

        List<FacilityDO> facilityDOList = facilityMapper.selectBatchIds(updateReqVO.getIds());
        if (CollUtil.isNotEmpty(facilityDOList)) {
            UserDO userDO = userService.getById(updateReqVO.getUserId());

            List<ReceiveReturnDO> receiveReturnDOList = new ArrayList<>();
            List<FacilityDO> updateBatch = facilityDOList.stream().map(item -> {

                if (Objects.equals(updateReqVO.getType(), TypeEnum.RETURN.getType())) {


                    ReceiveReturnDO returnDO = new ReceiveReturnDO();
                    returnDO.setId(item.getReceiveReturnId());
                    returnDO.setReturnTime(LocalDateTimeUtil.convertStr());

                    UserDO user = userService.getById(item.getUserId());
                    if (user != null) {
                        returnDO.setReturnUser(user.getName());
                    }
                    returnDO.setType(updateReqVO.getType());

                    item.setReceiveReturnId(null);
                    item.setStatus(YesNoEnum.YES.getType());
                    item.setUserId(null);

                    receiveReturnDOList.add(returnDO);
                }else {
                    long nextId = IdUtil.getSnowflakeNextId();
                    item.setReceiveReturnId(nextId);
                    item.setStatus(YesNoEnum.NO.getType());
                    item.setUserId(updateReqVO.getUserId());

                    ReceiveReturnDO returnDO = new ReceiveReturnDO();
                    returnDO.setId(nextId);
                    returnDO.setFacilityId(item.getId());
                    returnDO.setFacilityName(item.getName());
                    returnDO.setCategoryName(item.getCategoryName());
                    returnDO.setFacilityNo(item.getNo());
                    returnDO.setUserId(updateReqVO.getUserId());
                    returnDO.setUserName(userDO.getName());
                    returnDO.setCreateTime(LocalDateTimeUtil.convertStr());
                    returnDO.setUpdateTime(LocalDateTimeUtil.convertStr());
                    returnDO.setType(updateReqVO.getType());
                    receiveReturnDOList.add(returnDO);
                }


                return item;
            }).collect(Collectors.toList());


            updateBatchById(updateBatch);

            returnService.saveOrUpdateBatch(receiveReturnDOList);
        }
    }

    @Override
    public List<FacilityDO> getFacilityList() {
        LambdaQueryWrapper<FacilityDO> lqw = new LambdaQueryWrapper<>();
        lqw.eq(FacilityDO::getStatus, YesNoEnum.YES.getType());
        return facilityMapper.selectList(lqw);
    }

    @Override
    public FacilityDO getByNo(String no, Integer type) {
        if (StrUtil.isBlank(no)) {
            return null;
        }
        if (type == null) {
            throw new RuntimeException("类型不能为空");
        }
        LambdaQueryWrapper<FacilityDO> lqw = new LambdaQueryWrapper<>();
        lqw.eq(FacilityDO::getNo, no);
        lqw.eq(FacilityDO::getStatus, type);
        //查询一条
        return facilityMapper.selectOne(lqw);
    }
}